package com.gopay.bis.nucc.expay.impl;

import com.gopay.bis.nucc.common.util.NuccHttpClientUtil;
import com.gopay.bis.nucc.expay.operation.NuccExPayCertHelper;
import com.gopay.common.cache.client.RedisClient;
import com.gopay.common.constants.bank.NuccConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.nucc.expay.NuccExpayBaseMessage;
import com.gopay.common.domain.bank.nucc.expay.cert.res.NuccExpayCertRes;
import com.gopay.common.domain.bank.nucc.expay.common.NuccExpayCommonRes;
import com.gopay.common.domain.bank.nucc.expay.pay.res.NuccExpaymentRes;
import com.gopay.common.domain.bank.nucc.expay.query.res.NuccExpayQueryRes;
import com.gopay.common.domain.bank.nucc.expay.refund.res.NuccExpayRefundRes;
import com.gopay.common.domain.bank.nucc.expay.rescind.res.NuccExpayRescindRes;
import com.gopay.common.domain.bank.nucc.expay.serial.res.NuccExpaySerialBodyCtrlnbinfLst;
import com.gopay.common.domain.bank.nucc.expay.serial.res.NuccExpaySerialRes;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.businesses.ExPayService;
import com.gopay.remote.bank.businesses.SerialApplyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** 
 * 网联快捷实现类
 * @ClassName: NuccExPayBankServiceImpl 
 * @author w_jiqing 
 * @date 2017年7月14日 上午11:57:39  
 */ 
public class NuccExPayBankServiceImpl implements ExPayService,SerialApplyService{
    
    private static Logger logger = LoggerFactory.getLogger(NuccExPayBankServiceImpl.class);
    
    private NuccExPayCertHelper nuccExpayCertHelper;

    private NuccHttpClientUtil nuccHttpClientUtil;


    /**
     * 通用报文签名使用
     */
    @Override
    public Object sign(BaseMessage baseMsg) throws GopayException {
        NuccExpayCommonRes message = (NuccExpayCommonRes) baseMsg;
        try{
            message =(NuccExpayCommonRes) nuccExpayCertHelper.endSign(message);
        }catch (GopayException e) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6060,e);
        } catch (Exception ex) {
            logger.error("网联快捷终态通知同步响应异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6060,ex);
        }
        return message;
    }

    /**
     * 身份认证
     * @param baseMsg
     * @return
     * @throws GopayException
     */
    @Override
    public Object sendSms(BaseMessage baseMsg) throws GopayException {
        NuccExpayBaseMessage message= (NuccExpayBaseMessage) baseMsg;
        NuccExpayCertRes res =null;
        try{
            message = nuccExpayCertHelper.certEncrypt(message);
            message = nuccExpayCertHelper.sign(message);
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            map.put("ReservedField", message.getCardNo().substring(message.getCardNo().length()-4, message.getCardNo().length()));
            String response =  nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res =(NuccExpayCertRes) nuccExpayCertHelper.verify(response, NuccExpayCertRes.class);
            if(res != null){
                res.setSuccess(true);
            }
        }catch (GopayException e) {
            logger.error("网联快捷支付认证异常",e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6077,e);
        } catch (Exception ex) {
            logger.error("网联快捷支付认证异常",ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6077,ex);
        }
        return res;
    }
    

    /**
     * 签约
     * @param baseMsg
     * @return
     * @throws GopayException
     */
    @Override
    public Object checkSms(BaseMessage baseMsg) throws GopayException {
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) baseMsg;
        NuccExpayCertRes res = null;
        try{
            message = nuccExpayCertHelper.certEncrypt(message);
            message = nuccExpayCertHelper.sign(message);
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            map.put("ReservedField", message.getCardNo().substring(message.getCardNo().length()-4, message.getCardNo().length()));
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res =(NuccExpayCertRes) nuccExpayCertHelper.verify(response, NuccExpayCertRes.class);
            if(res != null){
                res.setSuccess(true);
            }
        }catch (GopayException e) {
            logger.error("网联快捷支付签约异常",e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6078,e);
        } catch (Exception ex) {
            logger.error("网联快捷支付签约异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6078,ex);
        }
        return res;
    }

    /**
     * 解约
     * @param baseMsg
     * @return
     * @throws GopayException
     */
    @Override
    public Object cancel(BaseMessage baseMsg) throws GopayException {
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) baseMsg;
        NuccExpayRescindRes res = null;
        try{
            message = nuccExpayCertHelper.sign(message);
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            map.put("ReservedField", message.getCardNo().substring(message.getCardNo().length()-4, message.getCardNo().length()));
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res =(NuccExpayRescindRes) nuccExpayCertHelper.verify(response, NuccExpayRescindRes.class);
            if(res != null){
                res.setSuccess(true);
            }
        }catch (GopayException e) {
            logger.error("网联快捷支付解约异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6078,e);
        } catch (Exception ex) {
            logger.error("网联快捷支付解约异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6078,ex);
        }
        return res;
    }

    /**
     * 协议支付
     * @param baseMsg
     * @return
     * @throws GopayException
     */
    @Override
    public Object payment(BaseMessage baseMsg) throws GopayException {
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) baseMsg;
        NuccExpaymentRes res = null;
        try{
            message = nuccExpayCertHelper.sign(message);
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            map.put("ReservedField", message.getCardNo().substring(message.getCardNo().length()-4, message.getCardNo().length()));
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res = (NuccExpaymentRes) nuccExpayCertHelper.verify(response,  NuccExpaymentRes.class);
            if(res != null){
                res.setSuccess(true);
                if(res.getMsgBody()!=null&&res.getMsgBody().getSysRtnInf()!=null){
                	if(!NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())){
                		res.setBankRetCode(res.getMsgBody().getSysRtnInf().getSysRtnCd());
                		res.setReturnInfo(res.getMsgBody().getSysRtnInf().getSysRtnDesc());
                	}else if(res.getMsgBody().getBizInf()!=null){
                		res.setBankRetCode(res.getMsgBody().getBizInf().getBizStsCd());
                		res.setReturnInfo(res.getMsgBody().getBizInf().getBizStsDesc());
                	}
                }
            }
        }catch (GopayException e) {
            logger.error("网联快捷支付异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6057,e);
        } catch (Exception ex) {
            logger.error("网联快捷支付异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6057,ex);
        }
        return res;
    }

    /**
     *
     * @param baseMsg
     * @return
     * @throws GopayException
     */
    @Override
    public Object queryOrder(BaseMessage baseMsg) throws GopayException {
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) baseMsg;
        NuccExpayQueryRes res = null;
        try{
            message = nuccExpayCertHelper.sign(message);
            Map<String,String> map = new HashMap<String ,String>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res = (NuccExpayQueryRes) nuccExpayCertHelper.verify(response,  NuccExpayQueryRes.class);
            if(res != null){
                res.setSuccess(true);
            }
        }catch (GopayException e) {
            logger.error("网联快捷查询异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6058,e);
        } catch (Exception ex) {
            logger.error("网联快捷查询异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6058,ex);
        }
        return res;
    }
    
    @Override
    public Object refund(BaseMessage baseMsg) throws GopayException {
        NuccExpayBaseMessage message = (NuccExpayBaseMessage) baseMsg;
        NuccExpayRefundRes res = null;
        try{
            message = nuccExpayCertHelper.sign(message);           
            Map<String,String> map = new HashMap<String ,String>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            map.put("ReservedField", message.getCardNo().substring(message.getCardNo().length()-4, message.getCardNo().length()));
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res = (NuccExpayRefundRes) nuccExpayCertHelper.verify(response,  NuccExpayRefundRes.class);
            if(res != null){
                res.setSuccess(true);
            }
        }catch (GopayException e) {
            logger.error("网联快捷退款异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6087,e);
        } catch (Exception ex) {
            logger.error("网联快捷退款异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6087,ex);
        }
        return res;
    }
    
    @Override
    public Object verify(BaseMessage baseMsg) throws GopayException {
        ExPayBaseMessage message = (ExPayBaseMessage) baseMsg;
        try{
            return  nuccExpayCertHelper.verify(message);
        }catch (GopayException e) {
            logger.error("网联快捷解约验签异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6054,e);
        } catch (Exception ex) {
            logger.error("网联快捷解约验签异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6054,ex);
        }
    }
    
    @Override
    public synchronized void serialApply(BaseMessage baseMsg) throws GopayException {
        NuccExpayBaseMessage message =  (NuccExpayBaseMessage)baseMsg;
        NuccExpaySerialRes res = null;
        try{
            message = nuccExpayCertHelper.sign(message);            
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res = (NuccExpaySerialRes) nuccExpayCertHelper.verify(response,  NuccExpaySerialRes.class);
            if(res != null && NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())){
                List<NuccExpaySerialBodyCtrlnbinfLst> list = res.getMsgBody().getCtrlNbInf();
                if(list!= null && list.size()>0){
                    //按key清除之前的流水号缓存
                    RedisClient.del(NuccConstants.NUCC_SERIAL_REDIS_KEY);
                    int count = 0;
                    for(int i=0;i<list.size();i++){
                        NuccExpaySerialBodyCtrlnbinfLst clb =list.get(i);
                        //控制位前2位
                        String ctrlNbF = clb.getCtrlNbF();
                        //控制位后4位
                        String[] ctrlNbLs = clb.getCtrlNbL().split("\\|");
                        for(int j=0;j<ctrlNbLs.length;j++){
                            String ctrlNbL = ctrlNbLs[j];
                            RedisClient.hset(NuccConstants.NUCC_SERIAL_REDIS_KEY, NuccConstants.NUCC_SERIAL_REDIS_FIELD+count++, ctrlNbF+ctrlNbL);
                        }
                        
                    }
                }
            }else{
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E6120);
            }
        }catch (GopayException e) {
            logger.error("网联快捷流水号申请异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6120,e);
        } catch (Exception ex) {
            logger.error("网联快捷流水号申请异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6120,ex);
        }
    }
    
   
    @Override
    public Object signQuery(BaseMessage baseMsg) throws GopayException {
        // TODO Auto-generated method stub
        return null;
    }



    @Override
    public Object treatyQuery(BaseMessage baseMsg) throws GopayException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Object certification(BaseMessage baseMsg) throws GopayException {
        // TODO Auto-generated method stub
        return null;
    }  

    @Override
    public Object queryCvn(BaseMessage baseMsg) throws GopayException {
        // TODO Auto-generated method stub
        return null;
    }

    public NuccExPayCertHelper getNuccExpayCertHelper() {
        return nuccExpayCertHelper;
    }

    public void setNuccExpayCertHelper(NuccExPayCertHelper nuccExpayCertHelper) {
        this.nuccExpayCertHelper = nuccExpayCertHelper;
    }

    public NuccHttpClientUtil getNuccHttpClientUtil() {
        return nuccHttpClientUtil;
    }

    public void setNuccHttpClientUtil(NuccHttpClientUtil nuccHttpClientUtil) {
        this.nuccHttpClientUtil = nuccHttpClientUtil;
    }
}
